import os
import json
import difflib
from enum import Enum
from datetime import datetime, timedelta


class SigTestState(Enum):
    NOTHING_TO_DO = 0
    ERROR = 1  # 遇到错误了
    SAME = 2  # 没啥变化
    CHANGE = 3  # 有变化
    FIRST_INIT = 4  # 初次检测

    NEW_MEETING = 5
    HAVE_MEETING = 6
    ALARM_MEETING = 7
    NO_MEETING = 8


class Sig(object):
    workpath = ''
    spider = None

    def __init__(self, config):
        assert Sig.spider is not None
        self.name = config['name']
        self.etherpad = config["etherpad"]
        self.contacts = config['contacts']
        self.contacts_group = config['contacts_group']
        self._file_backup = os.path.join(Sig.workpath, f'{self.name}.pre')

        self.info = {
            "last_check": " - ",
            "last_change": " - ",

            "meeting": " - ",
            "meeting_time" : ""
        }
        self._info_backup = os.path.join(Sig.workpath, f'{self.name}.rcd')
        self.reload_info()

    def reload_info(self):
        if os.access(self._info_backup, os.F_OK):
            with open(self._info_backup, 'r') as f:
                info = json.load(f)
                for k in self.info:
                    self.info[k] = info.get(k) if info.get(k) is not None else " - "
            return

        with open(self._info_backup, 'w') as f:
            json.dump(self.info, f)

    def update_info(self, key, val):
        self.info[key] = val
        with open(self._info_backup, 'w') as f:
            json.dump(self.info, f)

    def get_content(self):
        url = '{}/export/txt'.format(self.etherpad)
        content_now = Sig.spider.get_text(url)
        if content_now is None:
            return None, None

        content_pre = None
        if os.access(self._file_backup, os.F_OK):
            with open(self._file_backup, 'r', encoding='utf-8') as f:
                lines = f.readlines()
                content_pre = ''.join(lines)

        # write backup file
        with open(self._file_backup, 'w', encoding='utf-8') as f:
            f.write(content_now)

        return content_pre, content_now

    def detect_change(self):

        pre_content, now_content = self.get_content()

        if pre_content is None and now_content is None:
            return SigTestState.ERROR, '出错啦'

        now = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        self.update_info('last_check', now)
        if pre_content is None:
            return SigTestState.FIRST_INIT, ''

        if pre_content == now_content:
            return SigTestState.SAME, ''

        self.update_info('last_change', now)
        diff = difflib.unified_diff(pre_content.splitlines(), now_content.splitlines(),
                                    lineterm='', fromfile='two hours ago', tofile='now')

        return SigTestState.CHANGE, '\n'.join(diff)

    def detect_meeting(self):
        now = datetime.now()
        url = f"https://opengauss.org/api-meeting/meetingsdata/?group={self.name}"
        data = Sig.spider.get_json(url)

        for day_schedule in data["tableData"]:
            if datetime.strptime(day_schedule["date"], '%Y-%m-%d') < now:
                continue
            
            for meeting in day_schedule["timeData"]:
                meeting_time_str = f'{day_schedule["date"]} {meeting["startTime"]}'
                meeting_time = datetime.strptime(meeting_time_str, '%Y-%m-%d %H:%M')
                if meeting_time < now:
                    continue

                if meeting["join_url"] == self.info["meeting"] and meeting_time_str == self.info["meeting_time"]:
                    res_state = SigTestState.HAVE_MEETING
                else:
                    res_state = SigTestState.NEW_MEETING
                    self.update_info("meeting", meeting["join_url"])
                    self.update_info("meeting_time", meeting_time_str)

                if timedelta() < meeting_time - now <= timedelta(minutes=5):
                    res_state = SigTestState.ALARM_MEETING

                return res_state, meeting_time_str, meeting["join_url"]

        self.update_info("meeting", '')
        self.update_info("meeting_time", '')
        return SigTestState.NO_MEETING, '', ''
        